package com.tanx.cqrs.saga.impl;

import com.tanx.cqrs.event.Event;
import com.tanx.cqrs.saga.SagaHandlerInstance;
import com.tanx.cqrs.saga.SagaInfo;
import com.tanx.cqrs.saga.SagaStoreRepository;

import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Consumer;
import java.util.function.Predicate;


public class MemorySagaStoreRepository implements SagaStoreRepository {
    private CopyOnWriteArraySet<MemorySagaInfoImpl> store = new CopyOnWriteArraySet<>();

    @Override
    public SagaInfo findSaga(String s, Class<?> aClass) {
        Optional<MemorySagaInfoImpl> first = store.stream().filter(new Predicate<MemorySagaInfoImpl>() {
            @Override
            public boolean test(MemorySagaInfoImpl mongoSagaInfo) {
                return mongoSagaInfo.getSagaId().equals(s);
            }
        }).findFirst();
        return first.orElse(null);
    }

    @Override
    public SagaInfo insertSaga(String s, SagaHandlerInstance sagaHandlerInstance, Event event) {
        MemorySagaInfoImpl info = new MemorySagaInfoImpl(s, sagaHandlerInstance, event);
        store.add(info);
        return info;
    }

    @Override
    public void endSaga(String s, SagaHandlerInstance sagaHandlerInstance, Event event) {
        store.stream().filter(new Predicate<MemorySagaInfoImpl>() {
            @Override
            public boolean test(MemorySagaInfoImpl mongoSagaInfo) {
                return mongoSagaInfo.getSagaId().equals(s);
            }
        }).forEach(new Consumer<MemorySagaInfoImpl>() {
            @Override
            public void accept(MemorySagaInfoImpl mongoSagaInfo) {
                mongoSagaInfo.getExecuteEvents().add(event);
                mongoSagaInfo.setStatus(SagaStatus.FINISH);
            }
        });
    }

    @Override
    public void updateSagaEventList(String s, Class<?> aClass, Event event) {
        store.stream().filter(new Predicate<MemorySagaInfoImpl>() {
            @Override
            public boolean test(MemorySagaInfoImpl mongoSagaInfo) {
                return mongoSagaInfo.getSagaId().equals(s);
            }
        }).forEach(new Consumer<MemorySagaInfoImpl>() {
            @Override
            public void accept(MemorySagaInfoImpl mongoSagaInfo) {
                mongoSagaInfo.getExecuteEvents().add(event);
            }
        });
    }

    @Override
    public String newUuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
}
